﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Runtime.Serialization;

namespace XC.DataAccess.EncoderDecoder.Services
{
    /// <summary>
    /// 编码服务
    /// </summary>
    internal class FrameEncodeService : FrameServicebase, IFrameEncodeService
    {
        /// <summary>
        /// 解码
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <returns></returns>
        /// <exception cref="EncodeException"></exception>
        public byte[]? Encoding<T>(T data)
        {
            if (data == null)
            {
                return null;
            }
            if (!keyValuePairs.ContainsKey(typeof(T)))
            {
                var proper = typeof(T).GetProperties();
                keyValuePairs.Add(typeof(T), proper.ToArray());
            }
            var properties = keyValuePairs[typeof(T)];
            List<byte> vs = new List<byte>();
            foreach (var item in properties)
            {
                var attr = (EncoderAttribute)Attribute.GetCustomAttribute(item, typeof(EncoderAttribute));
                if (attr != null && item.CanWrite && item.CanRead)
                {
                    if (attr.TypeConverter == null)
                    {
                        break;
                    }
                    var res = item.GetValue(data);
                    var converter = (IEncoderConverter)Activator.CreateInstance(attr.TypeConverter);
                    if (converter != null && res != null)
                    {
                        try
                        {
                            var buffer = converter.Encode(res,properties, data, attr);
                            if (buffer != null)
                            {
                                vs.AddRange(buffer);
                            }
                        }
                        catch (Exception err)
                        {
                            throw new EncodeException(item.Name, res, err.Message);
                        }
                    }
                }
            }
            return vs.ToArray();
        }
    }
}
